﻿using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using GIMS.Def;
using GIMS.Def.Arguments;
using GIMS.Def.Flags;
using GIMS.Def.Operators;
using GIMS.Def.Settings;
using GIMS.GUI.GraphManagement;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using GIMS.GUI.GraphItems;

namespace GIMS.GUI.Test
{
    /// <summary>
    ///This is a test class for ScriptCreatorTest and is intended
    ///to contain all ScriptCreatorTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ScriptCreatorTest
    {
        /// <summary>
        /// Reset GlobalSettings
        /// </summary>
        [TestInitialize()]
        public void MyTestInitialize()
        {
            GlobalSettings_Accessor.instance = null;
        }

        /// <summary>
        ///A test for getScript
        ///</summary>
        [TestMethod()]
        public void getScriptTest1()
        {
            MainWindowViewModel mWVM = createMainWindowViewModel1();
            ScriptCreator target = new ScriptCreator(mWVM);
            bool isExecutable;
            string script = target.GetScript(mWVM.Graph.GetSave(), out isExecutable);
            Assert.IsTrue(isExecutable);
            Assert.AreEqual(@"""image1.jpg"" ( ""image1.jpg"" -resize 50%% -resize 50%% ) ""image2.jpg"" -append ""ResultImage.jpg""", script);
        }

        /// <summary>
        ///A test for getScript (with Global Settings)
        ///</summary>
        [TestMethod()]
        public void getScriptTest2()
        {
            MainWindowViewModel mWVM = createMainWindowViewModel1();
            ScriptCreator target = new ScriptCreator(mWVM);
            SetSomeGlobalSettings();
            bool isExecutable;
            string script = target.GetScript(mWVM.Graph.GetSave(), out isExecutable);
            Assert.IsTrue(isExecutable);
            Assert.AreEqual(@"-size 22x11 -background rgba(0,0,255,1) ""image1.jpg"" ( ""image1.jpg"" -resize 50%% -resize 50%% ) ""image2.jpg"" -append ""ResultImage.jpg""", script);
            GlobalSettings_Accessor.instance = null;
        }

        private void SetSomeGlobalSettings()
        {
            List<Setting> settings=GlobalSettings.Instance.Settings;

            settings.First(x => x.Name.Equals("Background")).Active=true;
            ColorArgument colorArg = (ColorArgument)settings.First(x => x.Name.Equals("Background")).Argument;
            colorArg.Color = Color.Blue;

            settings.First(x => x.Name.Equals("Size")).Active = true;
            GeometryArgument geometryArg = (GeometryArgument)settings.First(x => x.Name.Equals("Size")).Argument;
            geometryArg.Height = 11;
            geometryArg.Width = 22;
        }

        private MainWindowViewModel createMainWindowViewModel1()
        {
            var vm = new MainWindowViewModel();
            vm.CurrentProgram = Program.convert;

            var v1 = new CustomVertex(OperatorFactory.GetOperator("load"));
            var loadOp1 = v1.IMOperator as LoadOperator;
            var arg1 = loadOp1.Argument as PathArgument;
            arg1.Path = "image1.jpg";

            var v2 = new CustomVertex(OperatorFactory.GetOperator("resize"));
            var v3 = new CustomVertex(OperatorFactory.GetOperator("resize"));

            var v4 = new CustomVertex(OperatorFactory.GetOperator("load"));
            var loadOp2 = v4.IMOperator as LoadOperator;
            var arg2 = loadOp2.Argument as PathArgument;
            arg2.Path = "image2.jpg";

            var v5 = new CustomVertex(OperatorFactory.GetOperator("append"));

            var v6 = new CustomVertex(OperatorFactory.GetOperator("save"));
            var saveOp = v6.IMOperator as SaveOperator;
            var arg3 = saveOp.Argument as PathArgument;
            arg3.Path = "ResultImage.jpg";

            vm.Graph.AddVertexRange(new CustomVertex[] { v1, v2, v3, v4, v5, v6 });
            vm.Graph.AddNewEdgeBetween(v1, v2);
            vm.Graph.AddNewEdgeBetween(v1, v5);
            vm.Graph.AddNewEdgeBetween(v2, v3);
            vm.Graph.AddNewEdgeBetween(v3, v5);
            vm.Graph.AddNewEdgeBetween(v4, v5);
            vm.Graph.AddNewEdgeBetween(v5, v6);

            return vm;
        }

        /// <summary>
        ///A test for getScript
        ///</summary>
        [TestMethod()]
        public void getScriptTest3()
        {
            MainWindowViewModel mWVM = createMainWindowViewModel2();
            ScriptCreator target = new ScriptCreator(mWVM);
            bool isExecutable;
            string script = target.GetScript(mWVM.Graph.GetSave(), out isExecutable);
            Assert.AreEqual(@"( ""image1.jpg"" -resize 50%% ) ( ( ""image1.jpg"" -resize 50%% ) ( ""image2.jpg"" -resize 50%% -resize 50%% ) ""image3.jpg"" -append ) -append ""ResultImage.jpg""", script);
        }

        private MainWindowViewModel createMainWindowViewModel2()
        {
            var vm = new MainWindowViewModel();
            vm.CurrentProgram = Program.convert;

            var v1 = new CustomVertex(OperatorFactory.GetOperator("load"));
            var loadOp1 = v1.IMOperator as LoadOperator;
            var arg1 = loadOp1.Argument as PathArgument;
            arg1.Path = "image1.jpg";

            var v2 = new CustomVertex(OperatorFactory.GetOperator("load"));
            var loadOp2 = v2.IMOperator as LoadOperator;
            var arg2 = loadOp2.Argument as PathArgument;
            arg2.Path = "image2.jpg";

            var v3 = new CustomVertex(OperatorFactory.GetOperator("load"));
            var loadOp3 = v3.IMOperator as LoadOperator;
            var arg3 = loadOp3.Argument as PathArgument;
            arg3.Path = "image3.jpg";

            var v4 = new CustomVertex(OperatorFactory.GetOperator("resize"));
            var v5 = new CustomVertex(OperatorFactory.GetOperator("resize"));
            var v6 = new CustomVertex(OperatorFactory.GetOperator("resize"));
            var v7 = new CustomVertex(OperatorFactory.GetOperator("append"));
            var v8 = new CustomVertex(OperatorFactory.GetOperator("append"));
            var v9 = new CustomVertex(OperatorFactory.GetOperator("save"));
            var saveOp = v9.IMOperator as SaveOperator;
            var arg4 = saveOp.Argument as PathArgument;
            arg4.Path = "ResultImage.jpg";

            vm.Graph.AddVertexRange(new CustomVertex[] { v1, v2, v3, v4, v5, v6, v7, v8, v9 });
            vm.Graph.AddNewEdgeBetween(v1, v4);
            vm.Graph.AddNewEdgeBetween(v4, v7);
            vm.Graph.AddNewEdgeBetween(v4, v8);
            vm.Graph.AddNewEdgeBetween(v2, v5);
            vm.Graph.AddNewEdgeBetween(v5, v6);
            vm.Graph.AddNewEdgeBetween(v6, v7);
            vm.Graph.AddNewEdgeBetween(v3, v7);
            vm.Graph.AddNewEdgeBetween(v7, v8);
            vm.Graph.AddNewEdgeBetween(v8, v9);

            return vm;
        }

        /// <summary>
        ///A test for getScript
        ///</summary>
        [TestMethod()]
        public void getScriptTest4()
        {
            MainWindowViewModel mWVM = createMainWindowViewModel3();
            ScriptCreator target = new ScriptCreator(mWVM);
            bool isExecutable;
            string script = target.GetScript(mWVM.Graph.GetSave(), out isExecutable);
            Assert.AreEqual(@"( ""image1.jpg"" -resize 100 ) ( ( ""image1.jpg"" -resize 100 ) ( ""image2.jpg"" -resize 50%% -resize 50%% ) ""image3.jpg"" -append ) -append ""ResultImage.jpg""", script);
        }

        private MainWindowViewModel createMainWindowViewModel3()
        {
            Operator o1 = OperatorFactory.GetOperator("load");
            Operator o2 = OperatorFactory.GetOperator("load");
            Operator o3 = OperatorFactory.GetOperator("load");
            Operator o4 = OperatorFactory.GetOperator("resize");
            Operator o5 = OperatorFactory.GetOperator("resize");
            Operator o6 = OperatorFactory.GetOperator("resize");
            Operator o7 = OperatorFactory.GetOperator("append");
            Operator o8 = OperatorFactory.GetOperator("append");
            Operator o9 = OperatorFactory.GetOperator("save");

            GeometryArgument arg = (GeometryArgument)o4.Argument;
            arg.SelectedGeometryType=GeometryType.width;
            arg.Width = 100;

            GravitySetting grS=(GravitySetting)o7.Settings[0];
            

            var vm = new MainWindowViewModel();
            vm.CurrentProgram = Program.convert;

            var v1 = new CustomVertex(o1);
            var loadOp1 = v1.IMOperator as LoadOperator;
            var arg1 = loadOp1.Argument as PathArgument;
            arg1.Path = "image1.jpg";

            var v2 = new CustomVertex(o2);
            var loadOp2 = v2.IMOperator as LoadOperator;
            var arg2 = loadOp2.Argument as PathArgument;
            arg2.Path = "image2.jpg";

            var v3 = new CustomVertex(o3);
            var loadOp3 = v3.IMOperator as LoadOperator;
            var arg3 = loadOp3.Argument as PathArgument;
            arg3.Path = "image3.jpg";

            var v4 = new CustomVertex(o4);
            var v5 = new CustomVertex(o5);
            var v6 = new CustomVertex(o6);
            var v7 = new CustomVertex(o7);
            var v8 = new CustomVertex(o8);
            var v9 = new CustomVertex(o9);
            var saveOp = v9.IMOperator as SaveOperator;
            var arg4 = saveOp.Argument as PathArgument;
            arg4.Path = "ResultImage.jpg";

            vm.Graph.AddVertexRange(new CustomVertex[] { v1, v2, v3, v4, v5, v6, v7, v8, v9 });
            vm.Graph.AddNewEdgeBetween(v1, v4);
            vm.Graph.AddNewEdgeBetween(v4, v7);
            vm.Graph.AddNewEdgeBetween(v4, v8);
            vm.Graph.AddNewEdgeBetween(v2, v5);
            vm.Graph.AddNewEdgeBetween(v5, v6);
            vm.Graph.AddNewEdgeBetween(v6, v7);
            vm.Graph.AddNewEdgeBetween(v3, v7);
            vm.Graph.AddNewEdgeBetween(v7, v8);
            vm.Graph.AddNewEdgeBetween(v8, v9);

            return vm;
        }

        /// <summary>
        ///A test for getScript (with isExecutable=false)
        ///</summary>
        [TestMethod()]
        public void getScriptTest5()
        {
            MainWindowViewModel mWVM = new MainWindowViewModel();
            mWVM.CurrentProgram = Program.convert;
            var v1 = new CustomVertex(OperatorFactory.GetOperator("load"));
            var v2 = new CustomVertex(OperatorFactory.GetOperator("resize"));
            var v3 = new CustomVertex(OperatorFactory.GetOperator("save"));
            mWVM.Graph.AddVertexRange(new CustomVertex[] { v1, v2, v3 });
            mWVM.Graph.AddNewEdgeBetween(v1, v2);
            mWVM.Graph.AddNewEdgeBetween(v2, v3);

            ScriptCreator target = new ScriptCreator(mWVM);
            bool isExecutable;

            string script = target.GetScript(v1, out isExecutable);
            Assert.IsFalse(isExecutable);

            PathArgument pathArg = (PathArgument) v1.IMOperator.Argument;
            pathArg.Path = "image1.jpg";
            script = target.GetScript(v2, out isExecutable);
            Assert.IsTrue(isExecutable);


            script = target.GetScript(v3, out isExecutable);
            Assert.IsFalse(isExecutable);
        }
    }
}
